// Copyright (C) 2022 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
//
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<广西木子科技有限公司>，授权编号：<NT220402151538>，代码指纹：<A.648883738.885>，技术对接人微信：<ID: Lingmuziyi>】
// 【授权寄送：<收件：李先生、地址：南宁市科园西十路11号国电智能大厦1101F、电话：17736659550、邮箱：yingshashou@vip.qq.com>】
//
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
//
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rainbowchat.http.logic;

import java.io.File;
import java.util.HashMap;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.eva.epc.common.util.CommonUtils;
import com.eva.epc.common.util.RestHashMap;
import com.eva.framework.Processor;
import com.eva.framework.dbpool.DBShell;
import com.eva.framework.dto.SysActionConst;
import com.eva.framework.utils.EndsExceptionFactory;
import com.eva.framework.utils.LoggerFactory;
import com.x52im.rainbowchat.http.file.dto.BigFileType;
import com.x52im.rainbowchat.http.file.u.BigFileUploder;
import com.x52im.rainbowchat.http.file.u.ShortVideoUploader;

/**
 * 大文件信息相关的Http接口处理器实现类。
 *
 * @author Jack Jiang
 * @since 4.3
 */
public class FileInfoProcessor implements SysActionConst, Processor {
    public static DBShell db = new DBShell();

    /**
     * 处理器的核心实现方法.<br>
     * 可据job_dispatch_id找到对应的JobDispatcher，JobDispatcher又能据
     * action_id进行对应动作的处理，以完成本次操作请求.
     *
     * @param job_dispatch_id 作业调度ID
     * @param action_id       动作ID
     * @param Object          newData 客端发送过来的本次修改新数据(可能为空，理论上与oldData不会同时空）
     * @param Object          oldData 客端发送过来的本次修改前的老数据(可能为空，理论上与newData不会同时空）
     * @param UserRoot        user 包含该请求用户完整个人信息封装对象（该对象来自于成功登陆后存放于session中的值）
     * @return 任意类型返回值
     * @throws Exception
     */
    @Override
    public Object process(int job_dispatch_id, int action_id, Object _newData, Object _oldData, User user)
            throws Exception {
        Object ret = null;
        String newDataJSON = (String) _newData;

        switch (job_dispatch_id) {
            // 处理服务端对外提供的文件信息查询等
            case com.x52im.rainbowchat.http.logic.dto.JobDispatchConst.LOGIC_FILE_MGR:
                ret = maintainMgrFileJobDispatcher(action_id, newDataJSON, _oldData, user);
                break;
            default:
                throw EndsExceptionFactory.INVALID_JOB_DISPATCHER_ID(job_dispatch_id);
        }
        return ret;
    }

    /**
     * 维护文件信息查询等请求.
     *
     * @param action_id 维护类型，SysConstant中的操作类型常量
     * @param newData   客端发送过来的本次修改新数据(可能为空，理论上与oldData不会同时空）
     * @param oldData   客端发送过来的本次修改前的老数据(可能为空，理论上与newData不会同时空）
     * @param userName  操作者的用户名
     * @return 返回给客户端的对象
     */
    public String maintainMgrFileJobDispatcher(int action_id
            , Object newData, Object oldData, User user) throws Exception {
        switch (action_id) {
            // 【接口1015-23-7】获取指定md5码的大文件上传信息
            case ACTION_APPEND1: {
                JSONObject nwObj = JSONObject.parseObject((String) newData);

                // 要查询的文件md5码（查询时确保是用小写）
                String fileMd5 = nwObj.getString("file_md5").toLowerCase();
                // 用户的uid
                String userUid = nwObj.getString("user_uid");
                // 文件类型（@since 4.4）
                String fileTypeStr = nwObj.getString("file_type");
                int fileType = BigFileType.FILE_TYPE_COMMON_BIG_FILE;
                if (!CommonUtils.isStringEmpty(fileTypeStr))
                    fileType = CommonUtils.getIntValue(fileTypeStr, BigFileType.FILE_TYPE_COMMON_BIG_FILE);

                String retCode = "-1";
                int chunkCount = -1;

                // 首先：查询该文件信息是否已存在于missu_big_files表中，存在即表示它已经被上传，且上传完成
                // [说明]：本表的存在，是为了在文件数量庞大或文件被分布式存储等情况下，提供统一的文件信息检索能力，
                //       而不至于直接搜索文件存储目录看看文件存不存在这种方法（既低效，且方案也受限——因为文件被分
                //       布式存储或转储等情况，就没法查到信息了）。
                if (db.queryData("select 1 from missu_big_files where res_md5='" + fileMd5 + "' and file_status=0").size() > 0) {
                    retCode = "1";   //* 1 表示该文件已经存在且已上传完成（无需再次上传）
                }
                // 其次：再看看此文件是否未被上传完成（或根本没有上传过）
                else {
                    // 看看是否存在该文件的分块（存在分块则表示文件已被上传过，只是没有传完而已）
                    File bigFileChunkSavedDir = null;

                    if (fileType == BigFileType.FILE_TYPE_COMMON_BIG_FILE) {
                        bigFileChunkSavedDir = new File(BigFileUploder.getChunckCommonBigFileDir(fileMd5, userUid));
                    } else if (fileType == BigFileType.FILE_TYPE_SHORT_VIDEO) {
                        bigFileChunkSavedDir = new File(ShortVideoUploader.getChunckShortVideoFileDir(fileMd5, userUid));
                    }

                    LoggerFactory.getLog().debug("[HTTP大文件信息查询] 要查询的文件分块临时目录："
                            + bigFileChunkSavedDir.getAbsolutePath());

                    if (bigFileChunkSavedDir.exists()) {
                        // 看看分块目录中已经上传了多少块（为>=0的整数，断点上传时分块数是从1开始编号的）
                        chunkCount = bigFileChunkSavedDir.listFiles().length;
                        retCode = "2";//* 2 表示该文件已经存在查未上传完成（此时chunkCount才有意义）
                    } else {
                        retCode = "0";//* 0 表示该文件不存在(未被上传过)
                    }
                }

                // 返回结果
                RestHashMap<String, Object> ret = RestHashMap.n()
                        .p("retCode", retCode)
                        .p("chunkCount", chunkCount + "");

                return JSON.toJSONString(ret);
            }

            default:
                throw EndsExceptionFactory.INVALID_ACTION_ID(action_id);
        }
    }
}
